﻿#region MIT Licenze
//The MIT License

//Copyright (c) 2008 Sebastian Faltoni, dotnetfireball.org

//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:

//The above copyright notice and this permission notice shall be included in
//all copies or substantial portions of the Software.

//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Windows;
using System.Windows.Media;
using Fireball.Extensions;
using System.Windows.Markup;

namespace Fireball.OpenXML.Word
{
   /* public class BorderSpace
    {
        private int _left;
        private int _right;
        private int _top;
        private int _bottom;

        /*public static readonly BorderSpace Empty;

        static BorderSpace()
        {
            Empty = new BorderSpace(0);
        }

        public int Bottom
        {
            get { return _bottom; }
            set { _bottom = value; }
        }

        public int Top
        {
            get { return _top; }
            set { _top = value; }
        }

        public int Right
        {
            get { return _right; }
            set { _right = value; }
        }

        public int Left
        {
            get { return _left; }
            set { _left = value; }
        }

        public BorderSpace()
        {

        }

        public BorderSpace(int all)
        {
            this._left = this._right = this._bottom = this._top = all;
        }

        public BorderSpace(int left, int right, int top, int bottom)
        {
            this._left = left;
            this._right = right;
            this._top = top;
            this._bottom = bottom;
        }
    }

    /// <summary>
    /// 
    /// </summary>
    public class BorderColor
    {
        private Color _left;
        private Color _right;
        private Color _top;
        private Color _bottom;

/        public static readonly BorderColor Empty;

        static BorderColor()
        {
            Empty = new BorderColor(Colors.Transparent);
        }
        
        public Color Bottom
        {
            get { return _bottom; }
            set { _bottom = value; }
        }

        public Color Top
        {
            get { return _top; }
            set { _top = value; }
        }

        public Color Right
        {
            get { return _right; }
            set { _right = value; }
        }

        public Color Left
        {
            get { return _left; }
            set { _left = value; }
        }


        public BorderColor()
        {
           // this.Left = Colors.e
        }
        public BorderColor(Color all)
        {
            this._left = this._right = this._bottom = this._top = all;
        }

        public BorderColor(Color left, Color right, Color top, Color bottom)
        {
            this._left = left;
            this._right = right;
            this._top = top;
            this._bottom = bottom;
        }
    }
*/

    /// <summary>
    /// The Block Implementation as a Word Table
    /// </summary>
    [ContentProperty("Rows")]
    public class Table : Block, IFindable, IAddChild
    {
        private TableRowCollection _Rows = null;

        public Table()
        {
            _Rows = new TableRowCollection(this);
        }

        public TableRowCollection Rows
        {
            get
            {
                return _Rows;
            }
        }

        /*/// <summary>
        /// The size of the border
        /// </summary>
        public Thickness BorderSize
        {
            get;
            set;
        }*/

        /// <summary>
        /// Default margins for TableCell's of this Table
        /// </summary>
        public TableCellMarginDefaults TableCellMargin
        {
            get;
            set;
        }

       /* /// <summary>
        /// The space between the borders
        /// </summary>
        public BorderSpace BorderSpace
        {
            get;
            set;
        }*/

        /*/// <summary>
        /// The colors for the borders
        /// </summary>
        public BorderColor BorderColor
        {
            get;
            set;
        }*/

        #region BorderLeft
        private TableBorder _BorderLeft;

        public TableBorder BorderLeft
        {
            get
            {
                return _BorderLeft;
            }
            set
            {
                _BorderLeft = value;

                _BorderLeft.BorderKind = BorderKind.Left;
            }
        }

        #endregion

        #region BorderRight
        private TableBorder _BorderRight;

        public TableBorder BorderRight
        {
            get
            {
                return _BorderRight;
            }
            set
            {
                _BorderRight = value;

                _BorderRight.BorderKind = BorderKind.Right;
            }

        }
        #endregion

        #region BorderTop
        private TableBorder _BorderTop;

        public TableBorder BorderTop
        {
            get
            {
                return _BorderTop;
            }
            set
            {
                _BorderTop = value;

                _BorderTop.BorderKind = BorderKind.Top;
            }
        }
        #endregion

        #region BorderBottom
        private TableBorder _BorderBottom;

        public TableBorder BorderBottom
        {
            get
            {
                return _BorderBottom;
            }
            set
            {
                _BorderBottom = value;

                _BorderBottom.BorderKind = BorderKind.Bottom;
            }
        }
        #endregion

        /// <summary>
        /// The unit type used for  Width
        /// </summary>
        public WidthType WidthType
        {
            get;
            set;
        }

        /// <summary>
        /// The ID of the Associated Table Style
        /// </summary>
        public string Style
        {
            get;
            set;
        }

        public HorizontalAlignment? Alignment
        {
            get;
            set;
        }


        public override System.Xml.Linq.XContainer ToXml()
        {
            XElement xTable = new XElement(NS.WM + "tbl");/*
                new XElement(NS.WM + "tblPr",
                    new XElement(NS.WM + "tblW",
                        new XAttribute(NS.WM + "w", this.Width),
                        new XAttribute(NS.WM + "type", (this.Width == 0 ? "auto" : "pct"))),
                        GetBordersXml()),
                        new XElement(NS.WM + "tblGrid"),
                        (from p in this.Rows select p.ToXml()).ToArray()
                );*/

            XElement tblPr = new XElement(NS.WM + "tblPr");

            xTable.Add(tblPr);

            if (!string.IsNullOrEmpty(this.Style))
            {
                tblPr.Add(new XElement(NS.WM + "tblStyle",
                    new XAttribute(NS.WM + "val", this.Style)));
            }
            if (this.Width != null)
            {
                tblPr.Add(new XElement(NS.WM + "tblW",
                    new XAttribute(NS.WM + "w", this.Width.Value),
                    new XAttribute(NS.WM + "type", this.WidthType.ToOffice())));
            }
            if (this.Alignment != null)
            {
                tblPr.Add(new XElement(NS.WM + "jc",
                    new XAttribute(NS.WM + "val", this.Alignment.Value.ToOffice())));
            }
            #region Borders
            XElement tcBorders = new XElement(NS.WM + "tblBorders");

            if (this.BorderTop != null)
            {
                var bt = this.BorderTop.ToXml();

                if (bt != null)
                    tcBorders.Add(bt);
            }

            if (this.BorderLeft != null)
            {
                var bl = this.BorderLeft.ToXml();

                if (bl != null)
                    tcBorders.Add(bl);
            }

            if (this.BorderBottom != null)
            {
                var bb = this.BorderBottom.ToXml();

                if (bb != null)
                    tcBorders.Add(bb);
            }


            if (this.BorderRight != null)
            {
                var br = this.BorderRight.ToXml();

                if (br != null)
                    tcBorders.Add(br);
            }

            if (tcBorders.Elements().Count() > 0)
                tblPr.Add(tcBorders);
            #endregion Borders

            if (this.TableCellMargin != null)
                tblPr.Add(this.TableCellMargin.ToXml());

            xTable.Add(new XElement(NS.WM + "tblGrid"));

            var allRows = (from p in this.Rows select p.ToXml()).ToArray();

            xTable.Add(allRows);

            return xTable;
        }
        /*
        private XElement GetBordersXml()
        {
            var xBorders = new XElement(NS.WM + "tblBorders");

            if (this.BorderSize.Top > 0)
                xBorders.Add(new XElement(NS.WM + "top",
                        new XAttribute(NS.WM + "val", "single"),
                        new XAttribute(NS.WM + "sz", this.BorderSize.Top),
                        new XAttribute(NS.WM + "space", this.BorderSpace.Top),
                        new XAttribute(NS.WM + "color",
                           (this.BorderColor.Top == null ? "auto" : this.BorderColor.Top.ToHexFormat()))
                        ));
            else
                xBorders.Add(new XElement(NS.WM + "top",
                        new XAttribute(NS.WM + "val", "nil")));

            if (this.BorderSize.Left > 0)
                xBorders.Add(new XElement(NS.WM + "left",
                        new XAttribute(NS.WM + "val", "single"),
                        new XAttribute(NS.WM + "sz", this.BorderSize.Left),
                        new XAttribute(NS.WM + "space", this.BorderSpace.Left),
                        new XAttribute(NS.WM + "color",
                           (this.BorderColor.Left == null ? "auto" : this.BorderColor.Left.ToHexFormat()))
                        ));
            else
                xBorders.Add(new XElement(NS.WM + "left",
                        new XAttribute(NS.WM + "val", "nil")));

            if (this.BorderSize.Bottom > 0)
                xBorders.Add(new XElement(NS.WM + "bottom",
                        new XAttribute(NS.WM + "val", "single"),
                        new XAttribute(NS.WM + "sz", this.BorderSize.Bottom),
                        new XAttribute(NS.WM + "space", this.BorderSpace.Bottom),
                        new XAttribute(NS.WM + "color",
                           (this.BorderColor.Bottom == null ? "auto" : this.BorderColor.Bottom.ToHexFormat()))
                        ));
            else
                xBorders.Add(new XElement(NS.WM + "bottom",
                        new XAttribute(NS.WM + "val", "nil")));

            if (this.BorderSize.Right > 0)
                xBorders.Add(new XElement(NS.WM + "right",
                        new XAttribute(NS.WM + "val", "single"),
                        new XAttribute(NS.WM + "sz", this.BorderSize.Right),
                        new XAttribute(NS.WM + "space", this.BorderSpace.Right),
                        new XAttribute(NS.WM + "color",
                           (this.BorderColor.Right == null ? "auto" : this.BorderColor.Right.ToHexFormat()))
                        )
                        );
            else
                xBorders.Add(new XElement(NS.WM + "right",
                        new XAttribute(NS.WM + "val", "nil")));

            return xBorders;
        }
*/

        /// <summary>
        /// The Table with, keep null if you want word
        /// size automatically
        /// </summary>
        public int? Width
        {
            get;
            set;
        }

        #region IFindable Members

        public OpenXMLEntity FindByName(string name)
        {
            foreach (var r in this.Rows)
            {
                if (r.Name == name)
                    return r;

                var rs = r.FindByName(name);

                if (rs != null)
                    return rs;
            }
            return null;
        }

        #endregion

        #region IAddChild Members

        public void AddChild(object value)
        {
            if (!(value is TableRow))
                throw new Exception("Invalid child type a TableRow is required");
            this._Rows.Add((TableRow)value);
        }

        public void AddText(string text)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}
